package com.hh.service.impl;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.hh.common.ErrorCode;
import com.hh.entity.domain.Comments;
import com.hh.entity.domain.User;
import com.hh.entity.dto.comment.CommentsAddRequest;
import com.hh.entity.dto.comment.CommentsQueryRequest;
import com.hh.entity.vo.CommentTreeVO;
import com.hh.entity.vo.UserVO;
import com.hh.exception.ThrowUtils;
import com.hh.mapper.CommentsMapper;
import com.hh.service.CommentsService;
import com.hh.service.UserService;
import com.hh.utils.CommentTreeBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author hanhui
 * @description 针对表【comments】的数据库操作Service实现
 * @createDate 2025-07-20 12:03:00
 */
@Service
public class CommentsServiceImpl extends ServiceImpl<CommentsMapper, Comments>
        implements CommentsService {

    private static final List<String> sensitiveWords;

    static {
        try {
            ClassPathResource resource = new ClassPathResource("sensitive-words.json");
            InputStream inputStream = resource.getInputStream();
            String jsonContent = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
            sensitiveWords = new Gson().fromJson(jsonContent, new TypeToken<List<String>>() {
            }.getType());
        } catch (IOException e) {
            throw new RuntimeException("加载敏感词文件失败", e);
        }
    }

    @Resource
    private UserService userService;
    @Resource
    private CommentTreeBuilder commentTreeBuilder;

    @Override
    public boolean addComments(CommentsAddRequest commentsAddRequest, HttpServletRequest request) {
        //校验登录
        User currentUser = userService.getLoginUser(request);
        Long userId = currentUser.getId();
        ThrowUtils.throwIf(commentsAddRequest == null, ErrorCode.PARAMS_NULL);
        String content = commentsAddRequest.getContent();
        ThrowUtils.throwIf(StringUtils.isBlank(content), ErrorCode.PARAMS_NULL);
        //处理内容
        content = filterSensitiveWords(content);
        ThrowUtils.throwIf(content.length() > 1000, ErrorCode.PARAMS_ERROR);
        //处理敏感词
        content = filterInjection(content);
        ThrowUtils.throwIf(StringUtils.isBlank(content), ErrorCode.PARAMS_ERROR);
        String targetId = commentsAddRequest.getTargetId();
        ThrowUtils.throwIf(StringUtils.isBlank(targetId), ErrorCode.PARAMS_NULL);
        Integer targetType = commentsAddRequest.getTargetType();
        if (targetType == null) {
            targetType = 1;
        }
        Long parentId = commentsAddRequest.getParentId();
        if (parentId == null) {
            parentId = 0L;
        }
        Long rootId = commentsAddRequest.getRootId();
        if (rootId == null) {
            rootId = userId;
        }

        Comments comments = new Comments();
        comments.setContent(content);
        comments.setUserId(userId);
        comments.setTargetId(targetId);
        comments.setTargetType(targetType);
        comments.setParentId(parentId);
        comments.setRootId(rootId);
        comments.setStatus(0);
        comments.setCreatedTime(new Date());
        return this.save(comments);
    }

    @Override
    public QueryWrapper<Comments> getQueryWrapper(CommentsQueryRequest commentsQueryRequest) {
        ThrowUtils.throwIf(commentsQueryRequest == null, ErrorCode.PARAMS_NULL);
        String targetId = commentsQueryRequest.getTargetId();
        Integer replyCount = commentsQueryRequest.getReplyCount();
        Integer status = commentsQueryRequest.getStatus();
        Date createdTime = commentsQueryRequest.getCreatedTime();
        Date updatedTime = commentsQueryRequest.getUpdatedTime();
        int pageSize = commentsQueryRequest.getPageSize();
        int pageNum = commentsQueryRequest.getPageNum();
        String sortField = commentsQueryRequest.getSortField();
        String sortOrder = commentsQueryRequest.getSortOrder();


        QueryWrapper<Comments> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(targetId != null, "targetId", targetId);
        queryWrapper.eq(replyCount != null, "replyCount", replyCount);
        queryWrapper.eq(status != null, "status", status);
        queryWrapper.eq(createdTime != null, "createdTime", createdTime);
        queryWrapper.eq(updatedTime != null, "updatedTime", updatedTime);
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);

        return queryWrapper;
    }

    @Override
    public List<CommentTreeVO> getCommentsVOTree(List<Comments> commentsPage) {
        List<CommentTreeVO> commentTreeVOS = commentsPage.stream()
                .map(comment ->{
                    CommentTreeVO commentTreeVO = CommentTreeVO.objToVo(comment);
                    User user = userService.getById(comment.getUserId());
                    commentTreeVO.setUser(UserVO.objToVo(user));
                    return commentTreeVO;
                })
                .collect(Collectors.toList());

        return commentTreeBuilder.buildTree(commentTreeVOS);
    }

    @Override
    public boolean deleteComments(Long id, HttpServletRequest request) {
        return false;
    }

    @Override
    public boolean updateComments(Comments comments, HttpServletRequest request) {
        return false;
    }

    @Override
    public Comments getComments(Long id) {
        return null;
    }

    @Override
    public int getCommentsCount() {
        return 0;
    }

    @Override
    public int getCommentsCount(CommentsQueryRequest commentsQueryRequest) {
        return 0;
    }

    @Override
    public String filterSensitiveWords(String content) {
        if (content == null || sensitiveWords == null) {
            return content;
        }

        for (String word : sensitiveWords) {
            if (content.contains(word)) {
                // 替换为等长的*号
                StringBuilder stars = new StringBuilder();
                for (int i = 0; i < word.length(); i++) {
                    stars.append('*');
                }
                content = content.replace(word, stars.toString());
            }
        }
        return content;
    }

    @Override
    public String filterInjection(String content) {
        if (content == null) {
            return null;
        }
        // 防止 SQL 注入
        content = content.replaceAll("([';]+|(--)+)", "");
        // 防止 XSS 攻击
        content = content.replaceAll("<(?:script|img|style|link|meta|object|embed|frame|iframe|video|audio|source|track|canvas|svg|math|noscript|del|ins|map|area|base|basefont|bgsound|command|datalist|keygen|output|progress|time|mark|ruby|rt|rp|bdi|bdo|span|div|p|pre|blockquote|ol|ul|li|h1|h2|h3|h4|h5|h6|table|thead|tbody|tfoot|tr|th|td|col|colgroup|caption|form|input|textarea|select|option|optgroup|button|label|fieldset|legend|details|summary|menu|menuitem|dialog|menu|article|section|nav|aside|header|footer|address|main|figure|figcaption)(\s+[^>]*)?>", "");
        return content;
    }

}